home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Language/OS - Multiplatform Resource Library
/
LANGUAGE OS.iso
/
oper_sys
/
emerald
/
emrldsys.lha
/
Language
/
Compiler
/
genutils.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-08-16
|
39KB
|
1,577 lines
/*
* @(#)genutils.c 1.11 1/20/89
*/
#include "assert.h"
#include "addresses.h"
#include "nodes.h"
#include "map.h"
#include "sequence.h"
#include "system.h"
#include "builtins.h"
#include "evaluate.h"
#include "opNames.h"
#include "primitives.h"
#include "allocate.h"
#include "MyParser.h"
#include "datadesc.h"
#include "environment.h"
#include "regdefs.h"
#include "genutils.h"
#include "scan.h"
#include "semantics.h"
#include "emit.h"
#include "trace.h"
#include "flags.h"
#include "option.h"
/*
* Utility routines for writing to the code file.
*/
char *junk = "junk";
#ifdef vax
char *registerName[] = {
"r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
"r8", "r9", "r10", "r11", "r12", "r13", "sp", "pc", "junk"
};
#endif
#ifdef sun
char *registerName[] = {
"a0", "a1", "d0", "d1", "a2", "a3", "d2", "d3",
"d4", "d5", "d6", "a4", "a5", "a6", "sp", "pc", "junk"
};
#endif
typedef struct sHSEntry {
NodePtr p;
int startlabel;
int fhlabel;
int belabel;
int loopexitlabel;
struct sBEntry *parent;
struct sHSEntry *next;
} HSEntry, *HSEntryPtr;
static HSEntryPtr HSStackTop = NULL;
typedef struct sBEntry {
int bslabel;
int uhlabel;
int fhlabel;
int belabel;
struct sBEntry *parent;
} BEntry, *BEntryPtr;
static BEntryPtr BStackTop = NULL;
Boolean wroteCode;
static int lastLineNumber;
IPMapCollectorPtr lineNumberMap;
IPMapCollectorPtr unavailableHandlerMap;
IPMapCollectorPtr failureHandlerMap;
void initializeMaps()
{
int label = nextLabelNumber++;
lastLineNumber = -1;
wroteCode = FALSE;
if (! doGenerateCode) {
failureHandlerMap = createIPMap(label);
unavailableHandlerMap = createIPMap(label);
lineNumberMap = createIPMap(label);
}
BStackTop = NULL;
emit("L_%d:\n", label);
}
void forceLineNumber()
{
lastLineNumber = -1;
}
void lineNumberComment(p)
NodePtr p;
{
int label;
if ((lastLineNumber == -1 || wroteCode) && lastLineNumber != p->lineNumber){
label = nextLabelNumber++;
emit("L_%d:\t", label);
if (gtflag) {
#ifdef vax
emit("blbc\t*$ _emTracing,1f\n");
#endif
#ifdef sun
emit("tstl\t_emTracing\n");
emit("\tbeq\t1f\n");
#endif
emit("\tj%s\t%s_em_trace\n", JN(SUBR), GLOBALVARINDICATOR);
emit("1:\t");
}
if (lastLineNumber > 0)
addToIPMap(&lineNumberMap, label, -1, lastLineNumber);
Comment("\t\t\t\t\"%s\", line %d", currentFileName, p->lineNumber);
TRACE1(linenumber, 1, "Line number %d", p->lineNumber);
}
lastLineNumber = p->lineNumber;
wroteCode = FALSE;
}
void finalizeMaps()
{
int label = nextLabelNumber++;
emit("L_%d:\n", label);
addToIPMap(&failureHandlerMap, label, -1, 0);
addToIPMap(&unavailableHandlerMap, label, -1, 0);
addToIPMap(&lineNumberMap, label, -1, lastLineNumber);
}
Boolean mapHasEntries(m)
register IPMapCollectorPtr m;
{
if (m->nextToFill == 0) return(FALSE);
if (m->nextToFill == 1 && m->entry[0].dataLabel < 0 && m->entry[0].value == 0)
return(FALSE);
return(TRUE);
}
void dumpMaps()
{
if (! doGenerateCode) return;
if (mapHasEntries(failureHandlerMap)) {
emit("L_failureHandlerMap:\n");
dumpIPMap(failureHandlerMap);
}
if (mapHasEntries(unavailableHandlerMap)) {
emit("L_unavailableHandlerMap:\n");
dumpIPMap(unavailableHandlerMap);
}
if (mapHasEntries(lineNumberMap)) {
emit("L_lineNumberMap:\n");
dumpIPMap(lineNumberMap);
}
}
extern int indexSize;
char *addressToString(a)
Address a;
{
static char buffer[32];
if (a.base == Register) {
sprintf(buffer, "%s", RN(a.offset));
} else if (a.autoDecrement || a.autoIncrement) {
assert(a.offset == 0);
assert(! (a.autoDecrement && a.autoIncrement));
#ifdef vax
sprintf(buffer, "%s(%s)%s",
a.autoDecrement ? "-" : "",
RN(a.base),
a.autoIncrement ? "+" : "");
#endif
#ifdef sun
sprintf(buffer, "%s@%s", RN(a.base), a.autoDecrement ? "-" : "+");
#endif
} else {
if (a.hasIndex) {
#ifdef vax
sprintf(buffer, "%d(%s)[%s]", a.offset, RN(a.base), RN(a.indexReg));
#endif
#ifdef sun
assert(indexSize > 0);
if (indexSize == 1) {
sprintf(buffer, "%s@(%d,%s:l)", RN(a.base), a.offset, RN(a.indexReg));
} else {
sprintf(buffer, "%s@(%d,%s:l:%d)", RN(a.base), a.offset, RN(a.indexReg), indexSize);
}
#endif
} else if (a.offset == 0) {
#ifdef vax
sprintf(buffer, "(%s)", RN(a.base));
#endif
#ifdef sun
sprintf(buffer, "%s@", RN(a.base));
#endif
} else {
#ifdef vax
sprintf(buffer, "%d(%s)", a.offset, RN(a.base));
#endif
#ifdef sun
sprintf(buffer, "%s@(%d)", RN(a.base), a.offset);
#endif
}
}
return(buffer);
}
DD nullDD, pusher, popper, nilDD;
NodePtr nilNode;
Context anyContext, pslContext, pusherContext;
Boolean DDNeedsLabel(d)
DD d;
{
return(d.kind == DD_OIDToODP || d.kind == DD_OIDToODAP ||
d.kind == DD_AbCon || d.kind == DD_OIDToCodePtr);
}
#define abs(N) ((N) < 0 ? (-(N)) : (N))
void writeLabel(d, c)
DD d;
char c;
{
assert(d.kind == DD_Label);
if (d.value.label < 100) {
emit("%d%c", abs(d.value.label),
d.value.label < 0 ? 'b' : 'f');
} else {
emit("L_%d", d.value.label);
}
if (c != '\0') (void) emit("%c", c);
}
extern Boolean formatAs0r;
void writeDD(d, c)
DD d;
char c;
{
NodePtr p;
wroteCode = TRUE;
switch (d.kind) {
case DD_Label:
#ifdef sun
emit("pc@(");
#endif
if (d.value.label < 100) {
emit("%d%c", abs(d.value.label), d.value.label < 0 ? 'b' : 'f');
} else {
emit("L_%d", d.value.label);
}
#ifdef sun
emit("-.-2:l)");
#endif
break;
case DD_Address:
emit(addressToString(d.value.address));
break;
case DD_Manifest:
if (d.value.manifest & 0xc0000000) {
emit("%c0x%08x", IMMEDIATECHAR, d.value.manifest);
} else {
emit("%c%d", IMMEDIATECHAR, d.value.manifest);
}
break;
case DD_RealManifest:
#ifdef vax
emit("%c0f%s", IMMEDIATECHAR, d.value.realmanifest);
#endif
#ifdef sun
if (formatAs0r) {
emit("%c0r%s", IMMEDIATECHAR, d.value.realmanifest);
} else {
float f;
double atof();
f = atof(d.value.realmanifest);
emit("%c0x%08x", IMMEDIATECHAR, (* ((int *)&f)));
}
#endif
break;
case DD_PSLCondition:
assert(FALSE);
break;
case DD_OIDToODP:
emit("%c0xabcdef01", IMMEDIATECHAR);
p = OTLookup(d.value.id);
assert(p != NULL);
if (p->tag == P_OBLIT) {
if (!bflag) ensureGenerate(getCodeOID(p));
if (p->b.oblit.f.immutable) {
saveRelocationInfo(currentInstruction, 2, AR_OIDToODAP, d.value.id,
getCodeOID(p));
} else if (Zflag) {
saveRelocationInfo(currentInstruction, 2, AR_OIDToCheatingODP, d.value.id,
getCodeOID(p));
} else {
saveRelocationInfo(currentInstruction, 2, AR_OIDToODP, d.value.id,
getCodeOID(p));
}
} else {
assert(p->tag == P_ATLIT);
saveRelocationInfo(currentInstruction, 2, AR_OIDToODP, d.value.id,
OIDOfBuiltin(B_INSTCT, SIGNATUREINDEX));
}
break;
case DD_OIDToODAP:
emit("%c0xabcdef01", IMMEDIATECHAR);
saveRelocationInfo(currentInstruction, 2, AR_OIDToODAP, d.value.id, 0);
break;
case DD_OIDToCodePtr:
emit("%c0xabcdef01", IMMEDIATECHAR);
saveRelocationInfo(currentInstruction, 2, AR_OIDToCodePtr, d.value.id, 0);
break;
case DD_AbCon:
emit("%c0xabcdef01", IMMEDIATECHAR);
ensureGenerate(getDDAbstractType(d));
if (!bflag) ensureGenerate(getDDConcreteType(d));
saveRelocationInfo(currentInstruction, 2, AR_OIDOIDToAbCon,
getDDAbstractType(d), getDDConcreteType(d));
break;
default:
assert(FALSE);
break;
}
if (c != '\0') (void) emit("%c", c);
}
void debugDD(d)
DD d;
{
displayDD(stdout, d, '\n');
fflush(stdout);
}
void displayDD(f, d, c)
FILE *f;
DD d;
char c;
{
switch (d.kind) {
case DD_Label:
#ifdef sun
emit("pc@(");
#endif
if (d.value.label < 100) {
fprintf(f, "%d%c", abs(d.value.label),
d.value.label < 0 ? 'b' : 'f');
} else {
fprintf(f, "L_%d", d.value.label);
}
#ifdef sun
emit("-.-2)");
#endif
break;
case DD_Address:
fprintf(f, addressToString(d.value.address));
if (d.value.address.baseIsTemporary) {
if (d.value.address.base == Register) {
fprintf(f, " (t%s)", RN(d.value.address.offset));
} else if (d.value.address.base == regs_l) {
/* this really means free the temp stack storage */
fprintf(f, " (ts%d)", d.value.address.offset);
} else {
fprintf(f, " (t%s)", RN(d.value.address.base));
}
}
if (d.value.address.indexIsTemporary) {
fprintf(f, " (ti %s)", RN(d.value.address.indexReg));
}
break;
case DD_Manifest:
if (d.value.manifest & 0xc0000000) {
fprintf(f, "%c0x%08x", IMMEDIATECHAR, d.value.manifest);
} else {
fprintf(f, "%c%d", IMMEDIATECHAR, d.value.manifest);
}
break;
case DD_RealManifest:
#ifdef vax
fprintf(f, "%c0f%s", IMMEDIATECHAR, d.value.realmanifest);
#endif
#ifdef sun
if (formatAs0r) {
fprintf(f, "%c0r%s", IMMEDIATECHAR, d.value.realmanifest);
} else {
float fl;
double atof();
fl = atof(d.value.realmanifest);
fprintf(f, "%c0x%08x", IMMEDIATECHAR, (* ((int *)&fl)));
}
#endif
break;
case DD_PSLCondition:
fprintf(f, "psl %s", JN(d.value.condition.psl));
break;
case DD_OIDToODP:
fprintf(f, "OIDToODP 0x%08x", d.value.id);
break;
case DD_OIDToODAP:
fprintf(f, "OIDToODAP 0x%08x", d.value.id);
break;
case DD_OIDToCodePtr:
fprintf(f, "OIDToCodePtr 0x%08x", d.value.id);
break;
case DD_AbCon:
fprintf(f, "DD_AbCon 0x%08x 0x%08x",
getDDAbstractType(d), getDDConcreteType(d));
break;
default:
fprintf(f, "JUNK!");
break;
}
if (c == '\n' && d.kind != DD_AbCon) {
fprintf(f, " AT = 0x%08x\n", getDDAbstractType(d));
} else if (c != '\0') (void) fputc(c, f);
}
void generateKernelCall(opName)
char *opName;
{
Boolean checkJump;
if (!strcmp(opName, "em_stackCheck") ||
!strcmp(opName, "ems_compare") ||
!strcmp(opName, "emtime_compare") ||
!strcmp(opName, "em_invokeAssumptionFailure")) checkJump = FALSE;
else checkJump = TRUE;
if (checkJump) JUMPDEBUG();
emit("\tj%s\t%s_%s\n", JN(SUBR), GLOBALVARINDICATOR, opName);
if (checkJump) JUMPCHECK();
}
void writeData(n)
int n;
{
emit("\t.long\t%d\n", n);
}
void writeWord(n)
int n;
{
emit("\t.word\t%d\n", n);
}
void writeHex(n)
OID n;
{
emit("\t.long\t0x%.8x\n", n);
}
void writeHexComment(n, c)
OID n;
char *c;
{
emit("\t.long\t0x%.8x", n);
Comment(c);
}
static ODTag nullTag;
ODTag BuildTag(fBasicTag, fReplicated)
ODBasicTag fBasicTag;
Boolean fReplicated;
{
register ODTag t;
t = nullTag;
t.otherstuff = OBSCUREVALUE;
t.tag = fBasicTag;
t.replicated = fReplicated;
if (t.tag == GODataTag && fReplicated) {
/* We introduced LOTag to handle local objects, and at the moment,
* replicated objects are local.
*/
t.tag = LOTag;
}
return(t);
}
/*
* The IP to Template map is generated on the basis of well known names.
* All we need is the number of routines, and whether the initially,
* process, and recovery sections exist.
*/
/*
* The IPToLineNumber, IP to UnavailableHandler, and IP to FailureHandler
* maps are saved as code is generated. The failure and unavailable handler
* maps require a stack as they nest. The line number map is simple.
*/
#define NEWIPMAPCOLLECTOR(N) ((IPMapCollectorPtr) malloc(sizeof(IPMapCollector) +\
((N)-1)*3*sizeof(int)))
IPMapCollectorPtr createIPMap(lowCodeLabel)
int lowCodeLabel;
{
register IPMapCollectorPtr p;
p = NEWIPMAPCOLLECTOR(10);
p->maxSize = 10;
p->nextToFill = 0;
p->lowCodeLabel = lowCodeLabel;
return(p);
}
void addToIPMap(p, codeLabel, dataLabel, value)
IPMapCollectorPtr *p;
int codeLabel, dataLabel, value;
{
register IPMapCollectorPtr lp = *p;
register int index;
register IPMapCEntryPtr ipme;
if (doGenerateCode) return;
if (lp->nextToFill == 0) {
if (dataLabel < 0 && value == 0) {
/* this is a non-existant first entry */
lp->lowCodeLabel = codeLabel;
return;
}
} else {
ipme = &lp->entry[lp->nextToFill - 1];
if (ipme->dataLabel < 0 && dataLabel < 0) {
if (ipme->value == value) {
ipme->codeLabel = codeLabel;
return;
}
} else if (ipme->dataLabel == dataLabel) {
ipme->codeLabel = codeLabel;
return;
}
}
if (lp->nextToFill >= lp->maxSize) {
IPMapCollectorPtr np;
register int i;
np = NEWIPMAPCOLLECTOR((unsigned)2 * lp->maxSize);
np->maxSize = 2 * lp->maxSize;
np->nextToFill = lp->nextToFill;
np->lowCodeLabel = lp->lowCodeLabel;
for (i = 0; i < lp->maxSize; i++) {
np->entry[i] = lp->entry[i];
}
free((char *)lp);
*p = np;
lp = np;
}
index = lp->nextToFill;
lp->entry[index].codeLabel = codeLabel;
lp->entry[index].dataLabel = dataLabel;
lp->entry[index].value = value;
lp->nextToFill++;
}
void dumpIPMap(p)
register IPMapCollectorPtr p;
{
register int i;
i = p->nextToFill - 1;
if (i >= 0 && p->entry[i].dataLabel < 0 && p->entry[i].value == 0) {
i--;
p->nextToFill --;
}
if (p->nextToFill > 0) {
emit("\t.long\tL_%d - L_beginCDA\n",
i >= 0 ? p->entry[i].codeLabel : p->lowCodeLabel);
emit("\t.long\tL_%d - L_beginCDA\n", p->lowCodeLabel);
for (i = 0; i < p->nextToFill; i++) {
emit("\t.long\tL_%d - L_beginCDA\n", p->entry[i].codeLabel);
if (p->entry[i].dataLabel >= 0) {
emit("\t.long\tL_%d - L_beginCDA\n", p->entry[i].dataLabel);
} else {
writeData(p->entry[i].value);
}
}
}
if (doGenerateCode) free((char *) p);
}
/*
* The op vector is also done on the basis of well known names.
*/
/*
* Utility routines for saving relocation information and eventual writing to
* the code file.
*/
static RelocationInfoPtr relocPtr;
static unsigned int relocationSize;
void initializeRelocationInfo()
{
# define MINIMUMSIZE 50
relocPtr = NEWRelocationInfo(MINIMUMSIZE);
relocPtr->numEntries = 0;
relocationSize = MINIMUMSIZE;
# undef MINIMUMSIZE
}
void saveRelocationInfo(labelNumber, offset, kind, OID1, OID2)
int labelNumber, offset;
AR_Kind kind;
OID OID1, OID2;
{
register RelocationInfoPtr np;
register int i;
if (relocPtr->numEntries >= relocationSize) {
relocationSize *= 2;
np = NEWRelocationInfo(relocationSize);
np->numEntries = relocPtr->numEntries;
for (i = 0; i < relocPtr->numEntries; i++) {
np->relocation[i] = relocPtr->relocation[i];
}
free((char *) relocPtr);
relocPtr = np;
}
i = relocPtr->numEntries++;
relocPtr->relocation[i].kind = kind;
relocPtr->relocation[i].where = (labelNumber << 8) + offset;
relocPtr->relocation[i].theOID1 = OID1;
relocPtr->relocation[i].theOID2 = OID2;
}
void dumpRelocationInfo()
{
register int i;
register ARelocationPtr ar;
register int label, offset;
emit("L_relocInfoStart:\n");
writeData(relocPtr->numEntries);
for (i = 0; i < relocPtr->numEntries; i++) {
ar = &relocPtr->relocation[i];
label = (ar->where >> 8) & 0xffff;
offset = (ar->where) & 0xff;
#ifdef vax
emit("\t.long\t((L_%d-L_beginCDA+%d)<<8)+%d\n",
label, offset, (int) ar->kind);
#else
#ifdef sun
emit("\t.long\t(L_%d-L_beginCDA+%d)+((%d)*%d)\n",
label, offset, (int) ar->kind, 1<<24);
#endif
#endif
writeHex(ar->theOID1);
writeHex(ar->theOID2);
}
free((char *) relocPtr);
relocPtr = NULL;
}
/*
* Utility routines for saving templates for eventual output to the code file.
*/
typedef struct sTemplateDescription {
char *name;
int number;
TemplatePtr tp;
} TemplateDescription, *TemplateDescriptionPtr;
typedef struct sTDC {
int numEntries;
TemplateDescription td[12];
} TDC, *TDCPtr;
#define NEWTDC(N) ((TDCPtr) malloc(\
(unsigned) (sizeof(TDC) -\
12 * sizeof(TemplateDescription) +\
(N) * sizeof(TemplateDescription))))
static TDCPtr tdcPtr;
static int TDCSize;
static TemplatePtr tempPtr;
static unsigned int templateSize;
void initializeTemplates()
{
# define MINIMUMSIZE 50
tdcPtr = NEWTDC(MINIMUMSIZE);
TDCSize = MINIMUMSIZE;
tdcPtr->numEntries = 0;
# undef MINIMUMSIZE
}
extern char *strdup();
void setHasInvokeQueueBit(hasInvokeQueue)
Boolean hasInvokeQueue;
{
tdcPtr->td[tdcPtr->numEntries-1].tp->B.hasInvokeQueue = hasInvokeQueue;
}
void initializeTemplate(name, number, exclusiveAccess)
char *name;
int number;
Boolean exclusiveAccess;
{
register TDCPtr np;
register int i;
name = strdup(name);
if (tdcPtr->numEntries >= TDCSize) {
TDCSize *= 2;
np = NEWTDC(TDCSize);
np->numEntries = tdcPtr->numEntries;
for (i = 0; i < tdcPtr->numEntries; i++) {
np->td[i] = tdcPtr->td[i];
}
free((char *) tdcPtr);
tdcPtr = np;
}
# define MINIMUMSIZE 50
tempPtr = NEWTemplate(MINIMUMSIZE);
tempPtr->B.numEntries = 0;
templateSize = MINIMUMSIZE;
tdcPtr->td[tdcPtr->numEntries].name = name;
tdcPtr->td[tdcPtr->numEntries].number = number;
tdcPtr->td[tdcPtr->numEntries].tp = tempPtr;
tempPtr->B.exclusiveAccess = exclusiveAccess;
tempPtr->B.hasInvokeQueue = FALSE;
tempPtr->B.notUsed = 0;
tdcPtr->numEntries++;
# undef MINIMUMSIZE
}
static void checkForRoomInTemplate()
{
register TemplatePtr np;
register int i;
if (tempPtr->B.numEntries >= templateSize) {
templateSize *= 2;
np = NEWTemplate(templateSize);
np->B.numEntries = tempPtr->B.numEntries;
for (i = 0; i < tempPtr->B.numEntries; i++) {
np->entry[i] = tempPtr->entry[i];
}
free((char *) tempPtr);
tempPtr = np;
tdcPtr->td[tdcPtr->numEntries-1].tp = tempPtr;
}
}
void saveShortStaticTemplate(theBrand, paramInfo, elementBrand, count,
attachedFlag)
Brand theBrand, elementBrand;
ParamInfo paramInfo;
int count;
Boolean attachedFlag;
{
register ShortStatic t, ot;
checkForRoomInTemplate();
if (tempPtr->B.numEntries > (unsigned)0) {
ot = tempPtr->entry[tempPtr->B.numEntries-1].TE.SS;
if (ot.Format == ShortStaticF &&
ot.theBrand == theBrand &&
ot.paramInfo == paramInfo &&
ot.elementBrand == elementBrand &&
ot.attachedFlag == attachedFlag) {
ot.count += count;
tempPtr->entry[tempPtr->B.numEntries-1].TE.SS = ot;
return;
}
}
t.Format = ShortStaticF;
t.theBrand = theBrand;
t.paramInfo = paramInfo;
t.attachedFlag = attachedFlag;
t.elementBrand = elementBrand;
t.count = count;
tempPtr->entry[tempPtr->B.numEntries].TE.SS = t;
tempPtr->B.numEntries++;
}
void saveRegisterTemplate(theBrand, storedWhere, reg, count, attachedFlag)
Brand theBrand;
Placement storedWhere;
int reg, count;
Boolean attachedFlag;
{
register RegisterTE t;
register RegisterTE ot;
checkForRoomInTemplate();
if (tempPtr->B.numEntries > (unsigned)0) {
ot = tempPtr->entry[tempPtr->B.numEntries-1].TE.R;
if (ot.Format == RegisterF &&
ot.theBrand == theBrand &&
ot.storedWhere == storedWhere &&
ot.attachedFlag == attachedFlag) {
ot.count += count;
tempPtr->entry[tempPtr->B.numEntries-1].TE.R = ot;
return;
}
}
t.Format = RegisterF;
t.theBrand = theBrand;
t.storedWhere = storedWhere;
t.attachedFlag = attachedFlag;
t.unusedFlag = FALSE;
t.reg = reg;
t.count = count;
tempPtr->entry[tempPtr->B.numEntries].TE.R = t;
tempPtr->B.numEntries++;
}
extern char *brandNames[];
char *ParamInfoNames[] = {
"",
"arg",
"res",
"moveres"
};
void commentTemplate(t)
register TemplateEntryPtr t;
{
if (!doGenerateCode) return;
fprintf(codeFile, " %c ", COMMENTCHAR);
switch (t->TE.SS.Format) {
case ShortStaticF:
fprintf(codeFile,
"%3d %s%s %s",
t->TE.SS.count,
t->TE.SS.attachedFlag ? "attached " : "",
ParamInfoNames[(int)t->TE.SS.paramInfo],
brandNames[(int)t->TE.SS.theBrand]);
if (t->TE.SS.theBrand == VectorBrand)
fprintf(codeFile, " of %s",
brandNames[(int)t->TE.SS.elementBrand]);
break;
case RegisterF:
fprintf(codeFile, "%sregister %s",
t->TE.R.attachedFlag ? "attached " : "",
registerName[t->TE.R.reg]);
if (t->TE.R.count > 1)
fprintf(codeFile, " - %s", registerName[t->TE.R.reg+t->TE.R.count-1]);
fprintf(codeFile, " %s%s",
brandNames[(int)t->TE.R.theBrand],
t->TE.R.storedWhere == InRegister ? "" : " insavearea");
break;
default:
break;
}
(void) fputc('\n', codeFile);
}
void dumpTemplate(name, number, tp)
char *name;
int number;
TemplatePtr tp;
{
register int i;
register TemplateEntryPtr te;
emit(name, number);
emit(":\n");
writeTag(tp->B);
for (i = 0; i < tp->B.numEntries; i++) {
te = &tp->entry[i];
switch (te->TE.SS.Format) {
case ShortStaticF:
writeTag(te->TE.SS);
break;
case RegisterF:
writeTag(te->TE.R);
break;
default:
assert(FALSE);
break;
}
commentTemplate(te);
}
free((char *) tp);
}
void dumpTemplates()
{
register int i;
register TemplateDescriptionPtr td;
for (i = 0; i < tdcPtr->numEntries; i++) {
td = &tdcPtr->td[i];
dumpTemplate(td->name, td->number, td->tp);
}
free((char *) tdcPtr);
}
int findATOpNumber(at, opName)
NodePtr at, opName;
{
register NodePtr sigs, asig, aname;
register OID theID;
assert(at->tag == P_ATLIT);
assert(opName->tag == P_OPNAME);
theID = opName->b.opname.id;
sigs = at->b.atlit.ops;
assert(isASequence(sigs));
Sequence_For(asig, sigs)
assert(asig->tag == P_OPSIG);
aname = asig->b.opsig.name;
assert(aname->tag == P_OPNAME);
if (aname->b.opname.id == theID) return(z__z);
Sequence_Next
assert(FALSE);
/*NOTREACHED*/
}
NodePtr resolveOIDToCTOrAT(id)
OID id;
{
register NodePtr p, q = NULL;
register OID codeoid;
p = OTLookup(id);
assert((int)p != NIL);
if (p->tag == P_ATLIT) {
if (p->b.atlit.f.cannotBeConformedTo) {
codeoid = getCodeOID(p);
assert(codeoid != 0);
q = OTLookup(codeoid);
assert(q->tag == P_OBLIT);
assert(q != NULL);
p = q;
}
}
return(p);
}
NodePtr resolveToCTOrAT(p)
NodePtr p;
{
Symbol st;
OID id;
NodePtr q;
switch (p->tag) {
case P_GLOBALREF:
resolveGlobal(p, (ValuePtr) NULL);
return(resolveToCTOrAT(p->b.globalref.value));
/* break; */
case P_OBLIT:
return(p);
/* break; */
case P_ATLIT:
id = getCodeOID(p);
if (id != 0) {
q = OTLookup(id);
assert((int)q != NIL);
return(q);
} else if (p->b.atlit.f.writeSeparately) {
assert(p->b.atlit.id != 0);
return(resolveOIDToCTOrAT(p->b.atlit.id));
} else {
return(p);
}
/* break; */
case P_SYMREF:
st = ST_Fetch(p->b.symref.symbol);
assert(st->isManifest);
assert(st->value.value != NULL);
return(resolveToCTOrAT(st->value.value));
/* break; */
default:
assert(FALSE);
/*NOTREACHED*/
/* break; */
}
}
/*
* Return the best description of the entity that will result by executing
* the expression.
*/
NodePtr getBestInfoFromExpression(p)
register NodePtr p;
{
Symbol st;
assert ((int)p > 0x200);
switch (p->tag) {
case P_BUILTINLIT:
return(refToBuiltinFromToken(B_IT, p->b.builtinlit.whichType));
/* break; */
case P_INTLIT:
return(refToBuiltin(B_INSTCT, INTEGERINDEX));
/* break; */
case P_BOOLLIT:
return(refToBuiltin(B_INSTCT, BOOLEANINDEX));
/* break; */
case P_STRINGLIT:
return(refToBuiltin(B_INSTCT, STRINGINDEX));
/* break; */
case P_INVOC:
return(resolveOIDToCTOrAT(p->b.invoc.resultTypeOID));
/* break; */
case P_ATLIT:
return(refToBuiltin(B_INSTCT, SIGNATUREINDEX));
/* break; */
case P_GLOBALREF:
resolveGlobal(p, (ValuePtr) NULL);
return(getBestInfoFromExpression(p->b.globalref.value));
/* break; */
case P_OBLIT:
return(p);
/* break; */
case P_SYMREF:
st = ST_Fetch(p->b.symref.symbol);
if (st->value.CTinfo != NULL)
return(resolveToCTOrAT(st->value.CTinfo));
else
return(resolveToCTOrAT(st->value.ATinfo));
/* break; */
default:
assert(FALSE);
/*NOTREACHED*/
/* break; */
}
}
OID getCodeID(p)
NodePtr p;
{
NodePtr q;
p = GETVALUE(p);
if (p->tag == P_OBLIT) {
return(getCodeOID(p));
} else if (p->tag == P_BUILTINLIT) {
q = refToBuiltinFromToken(B_INSTAT, p->b.builtinlit.whichType);
q = resolveOIDToCTOrAT(q->b.atlit.id);
assert(q->tag == P_OBLIT);
return(getCodeOID(q));
} else if (p->tag == P_ATLIT) {
q = resolveOIDToCTOrAT(p->b.atlit.id);
assert(q->tag == P_OBLIT);
return(getCodeOID(q));
} else {
assert(FALSE);
/*NOTREACHED*/
}
}
OID getID(p)
NodePtr p;
{
return(GETVALUE(p)->b.oblit.id);
}
NodePtr getValue(p)
NodePtr p;
{
if (p->tag == P_GLOBALREF) {
resolveGlobal(p, (ValuePtr) NULL);
p = p->b.globalref.value;
}
assert(p->tag == P_ATLIT || p->tag == P_OBLIT);
return(p);
}
DD buildAbCon(ATID, CTID)
OID ATID, CTID;
{
DD result;
result.kind = DD_AbCon;
setDDConcreteType(result, CTID);
setDDAbstractType(result, ATID);
return(result);
}
DD buildAbConFromObject(p)
NodePtr p;
{
NodePtr q;
q = GETVALUE(p->b.oblit.myat);
assert(q->tag == P_ATLIT);
return(buildAbCon(q->b.atlit.id, getCodeOID(p)));
}
DD buildRegisterDD(registerNumber)
int registerNumber;
{
DD d;
d = nullDD;
d.kind = DD_Address;
d.value.address = nullAddress;
d.value.address.base = Register;
d.value.address.offset = registerNumber;
if (registerNumber < 0) {
implementationBug("Out of temporary registers");
} else if (registerNumber < 4) {
d.value.address.baseIsTemporary = TRUE;
ensureAllocated(registerNumber, 1);
}
return(d);
}
DD buildRegisterDDNC(registerNumber)
int registerNumber;
{
DD d;
d = nullDD;
d.kind = DD_Address;
d.value.address = nullAddress;
d.value.address.base = Register;
d.value.address.offset = registerNumber;
setDDAbstractType(d, OIDOfBuiltin(B_INSTAT, INTEGERINDEX));
return(d);
}
DD buildAddressDD(regNo, offset)
int regNo, offset;
{
DD d;
d = nullDD;
d.kind = DD_Address;
d.value.address.base = regNo;
d.value.address.offset = offset;
setDDAbstractType(d, OIDOfBuiltin(B_INSTAT, INTEGERINDEX));
return(d);
}
DD buildLabelDD(labelNumber)
int labelNumber;
{
DD d;
d = nullDD;
d.kind = DD_Label;
d.value.label = labelNumber;
return(d);
}
DD buildManifestDD(value)
int value;
{
DD d;
d = nullDD;
d.kind = DD_Manifest;
d.value.manifest = value;
return(d);
}
DD buildConCon(index)
int index;
{
NodePtr theAbObject;
theAbObject = refToBuiltin(B_INSTAT, index);
assert(theAbObject->tag == P_ATLIT);
if (theAbObject->b.atlit.f.cannotBeConformedTo) {
return(buildAbCon(OIDOfBuiltin(B_INSTAT, index),
OIDOfBuiltin(B_INSTCT, index)));
} else {
return(buildAbCon(OIDOfBuiltin(B_INSTCT, index),
OIDOfBuiltin(B_INSTCT, index)));
}
}
DD increaseIndirection(d)
DD d;
{
assert(d.kind == DD_Address);
assert(d.value.address.base == Register);
d.value.address.base = d.value.address.offset;
d.value.address.offset = 0;
return(d);
}
void freeDD(d)
DD d;
{
if (d.kind == DD_Address) {
if (d.value.address.baseIsTemporary) {
if (d.value.address.base == Register) {
freeReg((unsigned)d.value.address.offset, 1);
} else if (d.value.address.base == regs_l) {
/* this really means free the temp stack storage */
TS_Free(d.value.address.offset);
} else {
freeReg(d.value.address.base, 1);
}
}
if (d.value.address.indexIsTemporary) {
freeReg(d.value.address.indexReg, 1);
}
}
}
#ifdef TRASHOPNUMBERS
int translateATOpNumberToCTOpNumber(dd, abstractOpNumber)
DD dd;
int abstractOpNumber;
{
OID atOID, ctOID, opOID;
NodePtr at, ct;
register NodePtr p, ops;
int stage, concreteOpNumber;
Boolean found = FALSE;
assert(dd.kind == DD_AbCon);
atOID = getDDAbstractType(dd);
ctOID = getDDConcreteType(dd);
at = resolveOIDToCTOrAT(atOID);
ct = resolveOIDToCTOrAT(ctOID);
TRACE0(atctsort, 5, "translate at to ct op number:");
TRACE3(atctsort, 5, "at = %s ct = %s number = %d", ATName(at), ATName(ct),
abstractOpNumber);
if (at->tag == P_OBLIT) {
/*
* We know the concrete type given the abstract type, so we have the
* right operation number already.
*/
TRACE0(atctsort, 7, "Know ct");
concreteOpNumber = abstractOpNumber;
} else {
assert(at->tag == P_ATLIT);
assert(ct->tag == P_OBLIT);
p = at->b.atlit.ops;
assert(isASequence(p));
assert(abstractOpNumber >= 0 && abstractOpNumber < Sequence_Length(p));
p = p->b.children[abstractOpNumber];
assert(p->tag == P_OPSIG);
TRACE1(atctsort, 7, "Operation name = %s", SigName(p));
p = p->b.opsig.name;
assert(p->tag == P_OPNAME);
opOID = p->b.opname.id;
for (stage = 0; stage < 2 && !found; stage++) {
if (stage == 0) {
ops = ct->b.oblit.monitor;
if (ops != NULL) {
assert(ops->tag == P_MONITOR);
ops = ops->b.monitor.ops;
}
} else if (stage == 1) {
ops = ct->b.oblit.ops;
}
Sequence_For(p, ops)
assert(p->tag == P_OPDEF);
concreteOpNumber = p->b.opdef.opNumber;
p = p->b.opdef.sig;
assert(p->tag == P_OPSIG);
p = p->b.opsig.name;
assert(p->tag == P_OPNAME);
if (opOID == p->b.opname.id) {
found = TRUE;
break;
}
Sequence_Next
}
assert(found);
}
TRACE1(atctsort, 5, "returning %d", concreteOpNumber);
return(concreteOpNumber);
}
#endif
NodePtr getCTInfo(st)
register Symbol st;
{
register NodePtr ct;
if (st->value.CTinfo != NULL) {
ct = st->value.CTinfo;
} else {
ct = resolveToCTOrAT(st->value.ATinfo);
if (ct->tag != P_OBLIT) {
ct = NULL;
} else {
st->value.CTinfo = ct;
}
}
if (ct != NULL) ct = GETVALUE(ct);
return(ct);
}
NodePtr getBestInfoFromAbCon(d)
DD d;
{
OID ctoid;
NodePtr ct;
if (d.kind == DD_AbCon) {
ctoid = getDDConcreteType(d);
ct = OTLookup(ctoid);
assert(ct != NN);
assert(ct->tag == P_OBLIT);
} else {
ctoid = getDDAbstractType(d);
ct = resolveOIDToCTOrAT(ctoid);
assert(ct->tag == P_ATLIT || ct->tag == P_OBLIT);
}
return(ct);
}
NodePtr ATCTOIDToCTPtr(atoid, ctoid)
OID atoid, ctoid;
{
NodePtr ct;
if (ctoid != 0) {
ct = resolveOIDToCTOrAT(ctoid);
} else {
ct = resolveOIDToCTOrAT(atoid);
}
return(ct);
}
NodePtr getConcreteTypeFromAbCon(d)
DD d;
{
OID ctoid;
NodePtr ct;
assert(d.kind == DD_AbCon);
ctoid = getDDConcreteType(d);
ct = OTLookup(ctoid);
assert(ct != NN);
return(ct);
}
/*
* This one returns the symbol of the result of getelement on the
* given object constructor.
*/
Symbol getElementTypeSymbol(ct)
NodePtr ct;
{
register NodePtr p;
Symbol elementTypeSymbol;
char *getelementname = "getelement";
assert(ct->tag == P_OBLIT);
p = Construct(P_OPNAME, 0);
p->b.opname.ident = Ident_Lookup(getelementname, strlen(getelementname));
p->b.opname.id = ON_Translate(getelementname);
p = findObjectOperation(ct, p);
assert(p->tag == P_OPDEF);
p = p->b.opdef.sig;
assert(p->tag == P_OPSIG);
p = p->b.opsig.results->b.children[0]->b.param.sym;
assert(p != NULL);
assert(p->tag == P_SYMDEF);
elementTypeSymbol = ST_Fetch(p->b.symdef.symbol);
return(elementTypeSymbol);
}
int getSymbolSize(st)
Symbol st;
{
int size = -1;
AllocateKind ak;
ATCTToSizeAndKind(st->value.ATinfo, st->value.CTinfo, st->isAttached,
&size, &ak);
assert(size != -1);
return(size);
}
Brand oidToBrand(atoid)
OID atoid;
{
switch (atoid) {
case OIDOfBuiltin(B_INSTAT, BOOLEANINDEX):
case OIDOfBuiltin(B_INSTAT, REALINDEX):
case OIDOfBuiltin(B_INSTAT, CHARACTERINDEX):
case OIDOfBuiltin(B_INSTAT, INTEGERINDEX):
case OIDOfBuiltin(B_INSTCT, BOOLEANINDEX):
case OIDOfBuiltin(B_INSTCT, REALINDEX):
case OIDOfBuiltin(B_INSTCT, CHARACTERINDEX):
case OIDOfBuiltin(B_INSTCT, INTEGERINDEX):
return(DataBrand);
default:
return(ODPBrand);
}
}
Brand abConToBrand(d)
DD d;
{
OID atoid;
atoid = getDDAbstractType(d);
return(oidToBrand(atoid));
}
void HSPush(p, startlabel, fhlabel, belabel, loopexitlabel, parent)
NodePtr p;
int startlabel, fhlabel, belabel, loopexitlabel;
BEntryPtr parent;
{
register HSEntryPtr np;
TRACE4(handler, 1, "Push: start %d fh %d be %d parent %x", startlabel,
fhlabel, belabel, parent);
np = (HSEntryPtr) malloc(sizeof(HSEntry));
np->p = p;
np->startlabel = startlabel;
np->fhlabel = fhlabel;
np->belabel = belabel;
np->loopexitlabel = loopexitlabel;
np->parent = parent;
np->next = HSStackTop;
HSStackTop = np;
}
void HSDump()
{
HSEntryPtr p;
NodePtr handler;
Variable kernObject;
Symbol st;
int endlabel;
while (HSStackTop != NULL) {
p = HSStackTop;
HSStackTop = HSStackTop->next;
handler = p->p;
TRACE4(handler, 1, "HSDump: start %d fh %d be %d parent %x", p->startlabel,
p->fhlabel, p->belabel, p->parent);
assert(loops == NULL);
if (p->loopexitlabel != 0) {
loops = (LoopRecordPtr) malloc(sizeof(LoopRecord));
loops->label = p->loopexitlabel;
loops->enclosing = NULL;
}
#ifdef vax
emit("\t.byte\t0\n");
#endif
#ifdef sun
emit("\t.word\t0\n");
#endif
endlabel = nextLabelNumber++;
emit("L_%d:\n", p->startlabel);
IFOPTION(comment, 1)
Comment("\t\t\t\t%s handler start",
handler->tag == P_UNAVAILABLEHANDLER ? "unavailable" : "failure");
TS_fixSPForHandler();
if (handler->tag == P_UNAVAILABLEHANDLER) {
TRACE0(handler, 1, "unavailable handler");
BStackTop = p->parent;
TRACE1(handler, 1, "Popping stack to %x", BStackTop);
if (handler->b.unavailablehandler.decl != NULL) {
lineNumberComment(handler->b.unavailablehandler.decl);
st = ST_Fetch(handler->b.unavailablehandler.decl->b.vardecl.sym->b.symdef.symbol);
/* TODO: the run-time type check */
vPushVariable(st);
claimReg(regs_arg1, 2, VariableBrand);
kernObject.data = buildRegisterDD(regs_arg1);
kernObject.abCon = nextAddress(kernObject.data);
vPush(kernObject);
vGenerateAssign();
}
TRACE0(handler, 1, "generating handler");
generate(handler->b.unavailablehandler.body);
TRACE2(handler, 1, "add to failure code %d handler %d", endlabel,
p->fhlabel);
addToIPMap(&failureHandlerMap, endlabel, p->fhlabel, 0);
TRACE0(handler, 1, "Setting unavailable of stack top to -1");
BStackTop->uhlabel = -1;
} else if (handler->tag == P_FAILUREHANDLER) {
TRACE0(handler, 1, "failure handler");
BStackTop = p->parent;
TRACE1(handler, 1, "Popping stack to %x", BStackTop);
BStackTop->fhlabel =
BStackTop->parent == NULL ? -1 : BStackTop->parent->fhlabel;
TRACE1(handler, 1, "Setting failure handler of stack top to %d",
BStackTop->fhlabel);
generate(handler->b.failurehandler.body);
} else {
assert(FALSE);
}
emit("\tj%s\tL_%d\n", JN(ALWAYS), p->belabel);
emit("L_%d:\n", endlabel);
free((char *) p);
if (loops != NULL) {
free((char *)loops);
loops = NULL;
}
}
}
void blockStart(p)
NodePtr p;
{
int bslabel, uhlabel, fhlabel, belabel;
register BEntryPtr np;
bslabel = nextLabelNumber++;
belabel = nextLabelNumber++;
TRACE2(handler, 1, "Block start bs = %d be = %d", bslabel, belabel);
np = (BEntryPtr) malloc(sizeof(BEntry));
if (p->b.block.failurehandler != NN) {
fhlabel = nextLabelNumber++;
TRACE0(handler, 1, "block has failure handler push");
HSPush(p->b.block.failurehandler, fhlabel, -1, belabel,
loops == NULL ? 0 : loops->label, np);
} else if (BStackTop != NULL) {
/*
* we propogate the failure statically to the failure handler of
* the containing block.
*/
TRACE1(handler, 1, "block has no failure handler propogate to %d",
BStackTop->fhlabel);
fhlabel = BStackTop->fhlabel;
} else {
TRACE0(handler, 1, "block has no failure handler, no propogate possible");
fhlabel = -1;
}
if (p->b.block.unavailablehandler != NN) {
uhlabel = nextLabelNumber++;
TRACE0(handler, 1, "Block has unavailable handler push");
HSPush(p->b.block.unavailablehandler, uhlabel, fhlabel, belabel,
loops == NULL ? 0 : loops->label, np);
} else {
TRACE0(handler, 1, "Block has no unavailable handler");
uhlabel = -1;
}
emit("L_%d:\n", bslabel);
if (BStackTop != NULL) {
TRACE2(handler, 1, "add to unavailable code %d handler %d", bslabel,
BStackTop->uhlabel);
addToIPMap(&unavailableHandlerMap, bslabel, BStackTop->uhlabel, 0);
TRACE2(handler, 1, "add to failure code %d handler %d", bslabel,
BStackTop->fhlabel);
addToIPMap(&failureHandlerMap, bslabel, BStackTop->fhlabel, 0);
}
np->bslabel = bslabel;
np->uhlabel = uhlabel;
np->fhlabel = fhlabel;
np->belabel = belabel;
np->parent = BStackTop;
BStackTop = np;
TRACE5(handler, 1, "Pushing %x on stack: bs %d uh %d fh %d be %d", BStackTop,
bslabel, uhlabel, fhlabel, belabel);
}
void blockEnd()
{
BEntryPtr p = BStackTop;
BStackTop = p->parent;
TRACE1(handler, 1, "Popping stack to %x", BStackTop);
TRACE4(handler, 1, "block end: bs = %d uh = %d fh = %d be = %d",
p->bslabel, p->uhlabel, p->fhlabel, p->belabel);
emit("L_%d:\n", p->belabel);
TRACE2(handler, 1, "add to unavailable code %d handler %d", p->belabel, p->uhlabel);
addToIPMap(&unavailableHandlerMap, p->belabel, p->uhlabel, 0);
TRACE2(handler, 1, "add to failure code %d handler %d", p->belabel, p->fhlabel);
addToIPMap(&failureHandlerMap, p->belabel, p->fhlabel, 0);
}
void emitBranchOnBit(bitNumber, clearOrSet, regNo, label)
int bitNumber;
char clearOrSet;
int regNo;
DD label;
{
#ifdef vax
if (bitNumber == 0) {
emit("\tblb%c\t(%s),", clearOrSet, RN(regNo));
} else {
emit("\tbb%c\t%c%d,(%s),", clearOrSet, IMMEDIATECHAR, bitNumber, RN(regNo));
}
writeLabel(label, '\n');
#endif
#ifdef sun
int bitTstNumber, byteNumber;
PSLCondition c;
if (bitNumber == 0) {
emit("\ttstl\t%s@\n", RN(regNo));
c = (clearOrSet == 'c' ? PL : MI);
} else {
bitTstNumber = 7 - (bitNumber % 8);
byteNumber = bitNumber / 8;
if (byteNumber == 0) {
emit("\tbtst\t%c%d,%s@\n", IMMEDIATECHAR, bitTstNumber, RN(regNo));
} else {
emit("\tbtst\t%c%d,%s@(%d)\n", IMMEDIATECHAR, bitTstNumber, RN(regNo),
byteNumber);
}
c = (clearOrSet == 'c' ? EQL : NEQ);
}
emit("\tj%s\t", JN(c));
writeLabel(label, '\n');
#endif
}